package com.beantools.util;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.JSONScanner;
import com.alibaba.fastjson.util.IOUtils;
import com.beantools.entity.enums.DateFormatEnum;
import com.beantools.execption.ClassException;
import com.beantools.execption.JSONException;
import com.beantools.execption.PropertyException;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;

import static com.beantools.constants.FrameConstant.CONDITION_FALSE;
import static com.beantools.constants.FrameConstant.CONDITION_TRUE;
import static com.beantools.constants.MainASCCode.ASC_SERIES_COMMA_OP;
import static com.beantools.constants.SingleChar.*;
import static com.beantools.entity.enums.DateFormatEnum.ISO_DATETIME_FORMAT;
import static com.beantools.entity.enums.DateFormatEnum.ISO_DATE_FORMAT;
import static com.beantools.reflect.enums.EnumObjectJson.objToJson;
import static com.beantools.util.FastDateFormat.format;
import static com.beantools.util.FastDateFormat.parse;
import static com.beantools.util.ObjectUtil.isNotNull;
import static com.beantools.util.ObjectUtil.isNull;
import static com.beantools.util.StringUtil.isBlank;

/**
 * Created By zby on 11:54 2019/6/16
 * 这是将<code>Object</code>对象转化为指定的类型
 */

public class JavaTypeUtil {

    public JavaTypeUtil() {
    }

    public static String transformIntoString(Object value) {
        if (isNull(value)) {
            return null;
        }
        if (!(value instanceof String)) {
            throw new PropertyException("转化String失败，value=" + value);
        }
        return (String) value;
    }

    public static Byte transformIntoByte(Object value) {
        if (isNull(value)) {
            return null;
        }
        if (value instanceof Number) {
            return Byte.valueOf(((Number) value).byteValue());
        }
        if (value instanceof String) {
            String strVal = (String) value;
            return strVal.length() != 0 && !NULL.equalsIgnoreCase(strVal) ? Byte.valueOf(Byte.parseByte(strVal)) : null;
        }
        throw new PropertyException("转化为Byte异常, value : " + value);
    }

    public static Character transformIntoChar(Object value) {
        if (isNull(value)) {
            return null;
        } else if (value instanceof Character) {
            return (Character) value;
        } else if (value instanceof String) {
            String strVal = (String) value;
            if (isBlank(strVal)) {
                return null;
            } else if (strVal.length() != 1) {
                throw new PropertyException("转化Character失败，value=" + value);
            } else {
                return Character.valueOf(strVal.charAt(0));
            }
        }
        throw new PropertyException("转化Character失败，value=" + value);
    }

    public static Short transformIntoShort(Object value) {
        if (isNull(value)) {
            return null;
        } else if (value instanceof Number) {
            return Short.valueOf(((Number) value).shortValue());
        } else if (value instanceof String) {
            String strVal = (String) value;
            return strVal.length() != 0 && !NULL.equalsIgnoreCase(strVal) ? Short.valueOf(Short.parseShort(strVal)) : null;
        } else {
            throw new PropertyException("转化Short失败, value : " + value);
        }
    }

    public static BigDecimal transformIntoBigDecimal(Object value) {
        if (isNull(value)) {
            return null;
        } else if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        } else if (value instanceof BigInteger) {
            return new BigDecimal((BigInteger) value);
        }
        String strVal = value.toString();
        return strVal.length() == 0 ? null : new BigDecimal(strVal);
    }

    public static BigInteger transformIntoBigInteger(Object value) {
        if (isNull(value)) {
            return null;
        } else if (value instanceof BigInteger) {
            return (BigInteger) value;
        } else if (!(value instanceof Float) && !(value instanceof Double)) {
            String strVal = value.toString();
            return strVal.length() != 0 && !NULL.equalsIgnoreCase(strVal) ? new BigInteger(strVal) : null;
        }
        return BigInteger.valueOf(((Number) value).longValue());

    }

    public static Float transformIntoFloat(Object value) {
        if (value == null) {
            return null;
        } else if (value instanceof Number) {
            return Float.valueOf(((Number) value).floatValue());
        } else if (value instanceof String) {
            String strVal = value.toString();
            if (strVal.length() != 0 && !NULL.equalsIgnoreCase(strVal)) {
                if (strVal.indexOf(ASC_SERIES_COMMA_OP) != 0) {
                    strVal = strVal.replaceAll(SERIES_COMMA_OP, NULL_OP);
                }
                return Float.valueOf(Float.parseFloat(strVal));
            }
            return null;
        } else {
            throw new JSONException("转化Float失败, value : " + value);
        }
    }

    public static Double transformIntoDouble(Object value) {
        try {
            Float var = transformIntoFloat(value);
            return isNotNull(var) ? Double.valueOf(var).doubleValue() : null;
        } catch (Exception e) {
            throw new PropertyException("转化double失败，value=" + value);
        }
    }

    public static Date transformIntoDate(Object value, String dateFormat) {
        if (isNull(value)) {
            return null;
        } else if (value instanceof Date) {
            return getDate(dateFormat, (Date) value, ISO_DATETIME_FORMAT);
        } else if (value instanceof Calendar) {
            return ((Calendar) value).getTime();
        }
        long longValue = -1L;
        if (value instanceof Number) {
            longValue = ((Number) value).longValue();
            if (longValue < 0) {
                throw new PropertyException("转化date失败，value=" + value);
            }
            return getDate(dateFormat, new Date(longValue), ISO_DATETIME_FORMAT);
        }
        throw new PropertyException("转化date失败，value=" + value);
    }


    public static Date transformIntoDate(Object value, DateFormatEnum dateFormatEnum) {
        dateFormatEnum = isNull(dateFormatEnum) ? ISO_DATETIME_FORMAT : dateFormatEnum;
        return transformIntoDate(value, dateFormatEnum.value());
    }

    public static java.sql.Date transformIntoSqlDate(Object value, String dateFormat) {
        try {
            if (isNull(value)) {
                return null;
            } else if (value instanceof java.sql.Date) {
                return (java.sql.Date) getDate(dateFormat, (Date) value, ISO_DATE_FORMAT);
            } else {
                return (java.sql.Date) transformIntoDate(value, ISO_DATE_FORMAT);
            }
        } catch (Exception e) {
            throw new PropertyException("转化java.sql.Date失败，value=" + value);
        }
    }

    public static Timestamp transformIntoTimestamp(Object value) {
        try {
            if (isNull(value)) {
                return null;
            } else if (value instanceof Timestamp) {
                return (Timestamp) value;
            } else {
                return new Timestamp(transformIntoDate(value, ISO_DATE_FORMAT).getTime());
            }
        } catch (Exception e) {
            throw new PropertyException("转化Timestamp失败，value=" + value);
        }
    }

    public static Long transformIntoLong(Object value) {
        if (isNull(value)) {
            return null;
        } else if (value instanceof Number) {
            return Long.valueOf(((Number) value).longValue());
        } else {
            if (value instanceof String) {
                String strVal = (String) value;

                try {
                    if (strVal.length() != 0 && !NULL.equalsIgnoreCase(strVal)) {
                        if (strVal.indexOf(ASC_SERIES_COMMA_OP) != 0) {
                            strVal = strVal.replaceAll(SERIES_COMMA_OP, NULL_OP);
                        }
                        return Long.valueOf(Long.parseLong(strVal));
                    }
                    return null;
                } catch (NumberFormatException var4) {
                    JSONScanner dateParser = new JSONScanner(strVal);
                    Calendar calendar = null;
                    if (dateParser.scanISO8601DateIfMatch(false)) {
                        calendar = dateParser.getCalendar();
                    }
                    dateParser.close();
                    if (calendar != null) {
                        return Long.valueOf(calendar.getTimeInMillis());
                    }
                }
            }
            throw new JSONException("转化Long失败, value : " + value);
        }
    }

    public static Integer transformIntoInt(Object value) {
        if (value == null) {
            return null;
        } else if (value instanceof Integer) {
            return (Integer) value;
        } else if (value instanceof Number) {
            return Integer.valueOf(((Number) value).intValue());
        } else if (value instanceof String) {
            String strVal = (String) value;
            if (strVal.length() != 0 && !NULL.equalsIgnoreCase(strVal)) {
                if (strVal.indexOf(ASC_SERIES_COMMA_OP) != 0) {
                    strVal = strVal.replaceAll(SERIES_COMMA_OP, NULL_OP);
                }
                return Integer.valueOf(Integer.parseInt(strVal));
            }
            return null;
        } else if (value instanceof Boolean) {
            return Integer.valueOf(((Boolean) value).booleanValue() ? 1 : 0);
        } else {
            throw new JSONException("转化Integer失败, value :" + value);
        }
    }

    public static byte[] transformIntoBytes(Object value) {
        if (value instanceof byte[]) {
            return (byte[]) (value);
        } else if (value instanceof String) {
            return IOUtils.decodeBase64((String) value);
        } else {
            throw new JSONException("转化byte[]失败, value : " + value);
        }
    }

    public static Boolean transformIntoBoolean(Object value) {
        if (value == null) {
            return null;
        } else if (value instanceof Boolean) {
            return (Boolean) value;
        } else if (value instanceof Number) {
            return Boolean.valueOf(((Number) value).intValue() == 1);
        } else {
            if (value instanceof String) {
                String strVal = (String) value;
                if (strVal.length() == 0 || NULL.equalsIgnoreCase(strVal)) {
                    return null;
                }
                if (StringUtil.contains(CONDITION_TRUE, strVal)) {
                    return Boolean.TRUE;
                }
                if (StringUtil.contains(CONDITION_FALSE, strVal)) {
                    return Boolean.FALSE;
                }
            }

            throw new JSONException("转化Boolean失败, value : " + value);
        }
    }

    public static <T> JSONObject transformIntoEnum(Object obj) throws ClassException,PropertyException {
        JSONObject jsonObject;
        try {
            jsonObject = objToJson(obj);
        } catch (Exception e) {
            throw new ClassException(e.getMessage());
        }
        return jsonObject;
    }

    private static Date getDate(String dateFormat, Date var, DateFormatEnum dateFormatEnum) {
        dateFormat = isBlank(dateFormat) ? dateFormatEnum.value() : dateFormat;
        return parse(dateFormat, format(var, dateFormat));
    }
}
